{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Lab 3: Building a Travel Planner with a Simple LangGraph\n",
    "\n",
    "## Overview\n",
    "\n",
    "This lab guides you through the process of creating a simple Travel Planner using LangGraph, a library for building stateful, multi-step applications with language models. The Travel Planner demonstrates how to structure a conversational AI application that collects user input and generates personalized travel itineraries.\n",
    "\n",
    "## Intro to Agents\n",
    "- Agents are leverage LLM to `think step by step` and then plan the execution\n",
    "- Agents have access to tools\n",
    "- Agents have access to memory. Below diagram illustrates this concept\n",
    "\n",
    "#### Memory Management\n",
    "Memory is key for any agentic conversation which is `Multi-Turn` or `Multi-Agent` colloboration conversation and more so if it spans multiple days. The 3 main aspects of Agents are:\n",
    "1. Tools\n",
    "2. Memory\n",
    "3. Planners\n",
    "\n",
    "- ![Agent memory](./images/agents_memory_light.png)\n",
    "\n",
    "## Use Case Details\n",
    "\n",
    "Our Travel Planner follows a straightforward, three-step process:\n",
    "\n",
    "1. **Initial User Input**: \n",
    "   - The application prompts the user to enter their desired travel plan to get assistance from AI Agent.\n",
    "   - This information is stored in the state.\n",
    "\n",
    "2. **Interests Input**:\n",
    "   - The user is asked to provide their interests for the trip.\n",
    "   - These interests are stored as a list in the state.\n",
    "\n",
    "3. **Itinerary Creation**:\n",
    "   - Using the collected city and interests, the application leverages a language model to generate a personalized day trip itinerary.\n",
    "   - The generated itinerary is presented to the user.\n",
    "\n",
    "The flow between these steps is managed by LangGraph, which handles the state transitions and ensures that each step is executed in the correct order.\n",
    "\n",
    "The below diagram illustrates this:\n",
    "\n",
    "![Travel Planner Agent](./images/agents_itinerary.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup and Imports\n",
    "\n",
    "First, let's import the necessary modules and set up our environment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:23:52.691147Z",
     "start_time": "2025-02-13T20:23:52.660897Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from typing import TypedDict, Annotated, List\n",
    "from langgraph.graph import StateGraph, END\n",
    "from langchain_core.messages import HumanMessage, AIMessage\n",
    "from langchain_core.runnables.graph import MermaidDrawMethod\n",
    "from IPython.display import display, Image\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LangGraph -- State Graph, Nodes and Edges\n",
    "\n",
    "First, we are initializing the ```StateGraph```. This object will encapsulate the graph being traversed during excecution.\n",
    "\n",
    "Then we define the **nodes** in our graph. In LangGraph, nodes are typically python functions. There are two main nodes we will use for our graph:\n",
    "- The agent node: responsible for deciding what (if any) actions to take.\n",
    "- The tool node: This node will orchestrate calling the respective tool and returning the output. This means if the agent decides to take an action, this node will then execute that action.\n",
    "\n",
    "**Edges** define how the logic is routed and how the graph decides to stop. This is a big part of how your agents work and how different nodes communicate with each other. There are a few key types of edges:\n",
    "\n",
    "- Normal Edges: Go directly from one node to the next.\n",
    "- Conditional Edges: Call a function to determine which node(s) to go to next.\n",
    "- Entry Point: Which node to call first when user input arrives.\n",
    "- Conditional Entry Point: Call a function to determine which node(s) to call first when user input arrives.\n",
    "\n",
    "In our case we need to define a conditional edge that routes to the ```ToolNode``` when a tool get called in the agent node, i.e. when the LLM determines the requirement of tool use. With ```tools_condition```, LangGraph provides a preimplemented function handling this. Further, an edge from the ```START```node to the ```assistant```and from the ```ToolNode``` back to the ```assistant``` are required.\n",
    "\n",
    "We are adding the nodes, edges as well as a persistant memory to the ```StateGraph``` before we compile it. \n",
    "\n",
    "### Define Agent State\n",
    "\n",
    "We'll define the state that our agent will maintain throughout its operation. First, define the [State](https://langchain-ai.github.io/langgraph/concepts/low_level/#state) of the graph.  The State schema serves as the input schema for all Nodes and Edges in the graph.\n",
    "\n",
    "Let's use the `TypedDict` class from python's `typing` module as our schema, which provides type hints for the keys.\n",
    "\n",
    "### Key Components\n",
    "\n",
    "1. **StateGraph**: The core of our application, defining the flow of our Travel Planner.\n",
    "2. **PlannerState**: A custom type representing the state of our planning process.\n",
    "3. **Node Functions**: Individual steps in our planning process (input_city, input_interests, create_itinerary).\n",
    "4. **LLM Integration**: Utilizing a language model to generate the final itinerary.\n",
    "5. **Memory Integration**: Utilizing long term and short term memory for conversations\n",
    "\n",
    "#### Advanced concepts\n",
    "\n",
    "Now we'll define the main functions nodes that our agent will use: get interests, create itinerary. \n",
    "\n",
    "- [Nodes](https://langchain-ai.github.io/langgraph/concepts/low_level/#nodes) are python functions.\n",
    "- The first positional argument is the state, as defined above. \n",
    "- State is a `TypedDict` with schema as defined above, each node can access the key, `graph_state`, with `state['graph_state']`. \n",
    "- Each node returns a new value of the state key `graph_state`.\n",
    "  \n",
    "By default, the new value returned by each node [will override](https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers) the prior state value.\n",
    "\n",
    "### Memory\n",
    "\n",
    "1. We will disscuss memory is detail in subsequent sections below how some some key points\n",
    "2. We have `Conversational Memory` which is needed for all agents to have context since this is a `ChatBot` which needs history of conversations\n",
    "3. We usually summarize these into a **Summary Conversation** alternating with Human | AI for multi session conversations\n",
    "4. We have the concept of Graph State which is for Async workflows where we need to resume the workflow from a **certain point** in history\n",
    "\n",
    "For `A-Sync` workflows where we need to persist the state of the graph and bring it back once we get the required data. below diagram explains this concept. \n",
    "\n",
    "![Graph state](./images/graph_state_light.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define Agent Nodes\n",
    "\n",
    "we will create a simple graph with \n",
    "- user travel plans\n",
    "- invoke with Bedrock\n",
    "- generate the travel plan for the day \n",
    "- ability to add or modify the plan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:23:54.181480Z",
     "start_time": "2025-02-13T20:23:54.179440Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class PlannerState(TypedDict):\n",
    "    messages: Annotated[List[HumanMessage | AIMessage], \"The messages in the conversation\"]\n",
    "    itinerary: str\n",
    "    city: str\n",
    "    user_message: str"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set Up Language Model and Prompts\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:23:55.200748Z",
     "start_time": "2025-02-13T20:23:55.195691Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "\n",
    "from langchain_aws import ChatBedrockConverse\n",
    "import boto3\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "from langchain_core.runnables.config import RunnableConfig\n",
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "\n",
    "model_id = \"us.amazon.nova-lite-v1:0\"\n",
    "bedrock_client = boto3.client(\"bedrock-runtime\", region_name=\"us-west-2\")\n",
    "\n",
    "provider_id = \"amazon\"\n",
    "\n",
    "llm = ChatBedrockConverse(\n",
    "    model=model_id,\n",
    "    provider=provider_id,\n",
    "    temperature=0,\n",
    "    max_tokens=None,\n",
    "    client=bedrock_client,\n",
    ")\n",
    "\n",
    "\n",
    "itinerary_prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"You are a helpful travel assistant. Create a day trip itinerary for {city} based on the user's interests. Use the below chat conversation and the latest input from Human to get the user interests. Provide a brief, bulleted itinerary.\"),\n",
    "    MessagesPlaceholder(\"chat_history\"),\n",
    "    (\"human\", \"{user_message}\"),\n",
    "])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the nodes and Edges"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:23:56.358741Z",
     "start_time": "2025-02-13T20:23:56.356280Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def input_interests(state: PlannerState) -> PlannerState:\n",
    "    user_message = state['user_message']\n",
    "\n",
    "\n",
    "    if not state.get('messages', None) : state['messages'] = []\n",
    "    return {\n",
    "        **state,\n",
    "    }\n",
    "\n",
    "def create_itinerary(state: PlannerState) -> PlannerState:\n",
    "    response = llm.invoke(itinerary_prompt.format_messages(city=state['city'], user_message=state['user_message'], chat_history=state['messages']))\n",
    "    print(\"\\nFinal Itinerary:\")\n",
    "    print(response.content)\n",
    "    return {\n",
    "        **state,\n",
    "        \"messages\": state['messages'] + [HumanMessage(content=state['user_message']),AIMessage(content=response.content)],\n",
    "        \"itinerary\": response.content\n",
    "    }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create and Compile the Graph\n",
    "\n",
    "Now we'll create our LangGraph workflow and compile it. We build the graph from our [components](\n",
    "https://langchain-ai.github.io/langgraph/concepts/low_level/) defined above. The [StateGraph class](https://langchain-ai.github.io/langgraph/concepts/low_level/#stategraph) is the graph class that we can use.\n",
    " \n",
    "First, we initialize a StateGraph with the `State` class we defined above. Then, we add our nodes and edges. We use the [`START` Node, a special node](https://langchain-ai.github.io/langgraph/concepts/low_level/#start-node) that sends user input to the graph, to indicate where to start our graph. The [`END` Node](https://langchain-ai.github.io/langgraph/concepts/low_level/#end-node) is a special node that represents a terminal node. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:23:58.449213Z",
     "start_time": "2025-02-13T20:23:58.443962Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "workflow = StateGraph(PlannerState)\n",
    "\n",
    "#workflow.add_node(\"input_city\", input_city)\n",
    "workflow.add_node(\"input_interests\", input_interests)\n",
    "workflow.add_node(\"create_itinerary\", create_itinerary)\n",
    "\n",
    "workflow.set_entry_point(\"input_interests\")\n",
    "\n",
    "#workflow.add_edge(\"input_city\", \"input_interests\")\n",
    "workflow.add_edge(\"input_interests\", \"create_itinerary\")\n",
    "workflow.add_edge(\"create_itinerary\", END)\n",
    "\n",
    "# The checkpointer lets the graph persist its state\n",
    "# this is a complete memory for the entire graph.\n",
    "memory = MemorySaver()\n",
    "app = workflow.compile(checkpointer=memory)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Display the graph structure\n",
    "\n",
    "Finally, we [compile our graph](https://langchain-ai.github.io/langgraph/concepts/low_level/#compiling-your-graph) to perform a few basic checks on the graph structure. We can visualize the graph as a [Mermaid diagram](https://github.com/mermaid-js/mermaid)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:24:00.906601Z",
     "start_time": "2025-02-13T20:23:59.960457Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display(\n",
    "    Image(\n",
    "        app.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the function that runs the graph\n",
    "\n",
    "When we compile the graph, we turn it into a LangChain Runnable, which automatically enables calling `.invoke()`, `.stream()` and `.batch()` with your inputs. In the following example, we run `stream()` to invoke the graph with inputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:24:02.221502Z",
     "start_time": "2025-02-13T20:24:02.219758Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def run_travel_planner(user_request: str, config_dict: dict):\n",
    "    print(f\"Current User Request: {user_request}\\n\")\n",
    "    init_input = {\"user_message\": user_request,\"city\" : \"Seattle\"}\n",
    "\n",
    "    for output in app.stream(init_input, config=config_dict, stream_mode=\"values\"):\n",
    "        pass  # The nodes themselves now handle all printing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Travel Planner Example\n",
    "\n",
    "- To run this the system prompts and asks for user input for activities \n",
    "- We have initialized the graph state with city Seattle which usually will be dynamic and we will see in subsequrnt labs\n",
    "- You can enter like boating, swiming"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:24:46.977369Z",
     "start_time": "2025-02-13T20:24:42.730997Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current User Request: Can you create a itinerary for boating, swim. Need a complete plan\n",
      "\n",
      "\n",
      "Final Itinerary:\n",
      "Sure, here's a day trip itinerary for Seattle focusing on boating and swimming:\n",
      "\n",
      "### Seattle Boating and Swimming Day Trip Itinerary\n",
      "\n",
      "**8:00 AM - 9:00 AM: Breakfast at The Market by Jean-Georges**\n",
      "- Start your day with a delicious breakfast at this renowned restaurant.\n",
      "\n",
      "**9:30 AM - 11:00 AM: Rent a Boat at Leschi Boat Launch**\n",
      "- Head to Leschi Boat Launch to rent a boat. Enjoy the scenic views of Lake Washington.\n",
      "\n",
      "**11:00 AM - 12:30 PM: Boating on Lake Washington**\n",
      "- Cruise around Lake Washington, enjoying the beautiful scenery and fresh air.\n",
      "\n",
      "**12:30 PM - 1:30 PM: Lunch at Leschi Tavern**\n",
      "- Dock at Leschi Tavern for a casual lunch by the water.\n",
      "\n",
      "**1:30 PM - 2:30 PM: Boating to Magnuson Park**\n",
      "- Continue your boating adventure and head towards Magnuson Park.\n",
      "\n",
      "**2:30 PM - 3:30 PM: Swimming at Magnuson Park Beach**\n",
      "- Arrive at Magnuson Park and enjoy a swim in the lake. Relax on the sandy beach.\n",
      "\n",
      "**3:30 PM - 4:30 PM: Explore Magnuson Park**\n",
      "- Take a leisurely walk around the park, enjoying the natural beauty and playground.\n",
      "\n",
      "**4:30 PM - 5:30 PM: Return Boat and Drive to Fremont**\n",
      "- Return your boat and drive to the Fremont neighborhood.\n",
      "\n",
      "**5:30 PM - 6:30 PM: Dinner at Fremont Brewing Company**\n",
      "- Enjoy dinner at this popular spot, known for its craft beers and delicious food.\n",
      "\n",
      "**6:30 PM - 7:30 PM: Explore Fremont Troll**\n",
      "- Walk over to see the iconic Fremont Troll under the evening lights.\n",
      "\n",
      "**7:30 PM - 8:30 PM: Return Home**\n",
      "- Head back home, wrapping up a fantastic day of boating and swimming in Seattle.\n"
     ]
    }
   ],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "from IPython.display import display_markdown, Markdown\n",
    "user_request = \"Can you create a itinerary for boating, swim. Need a complete plan\"\n",
    "display_markdown(Markdown(run_travel_planner(user_request, config)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Leverage the memory saver to manipulate the Graph State\n",
    "- Since the `Conversation Messages` are part of the graph state we can leverage that\n",
    "- However the graph state is tied to `session_id` which will be passed in as a `thread_id` which ties to a session\n",
    "- If we add a request with different thread id it will create a new session which will not have the previous `Interests`\n",
    "- However this this has the other check points variables as well and so this pattern is good for `A-Sync` workflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:25:18.209485Z",
     "start_time": "2025-02-13T20:25:13.462204Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current User Request: Can you add white water rafting to this itinerary\n",
      "\n",
      "\n",
      "Final Itinerary:\n",
      "Absolutely! Here's an updated itinerary that includes white-water rafting:\n",
      "\n",
      "### Seattle Boating, Swimming, and White-Water Rafting Day Trip Itinerary\n",
      "\n",
      "**8:00 AM - 9:00 AM: Breakfast at The Market by Jean-Georges**\n",
      "- Start your day with a delicious breakfast at this renowned restaurant.\n",
      "\n",
      "**9:30 AM - 11:00 AM: Rent a Boat at Leschi Boat Launch**\n",
      "- Head to Leschi Boat Launch to rent a boat. Enjoy the scenic views of Lake Washington.\n",
      "\n",
      "**11:00 AM - 12:30 PM: Boating on Lake Washington**\n",
      "- Cruise around Lake Washington, enjoying the beautiful scenery and fresh air.\n",
      "\n",
      "**12:30 PM - 1:30 PM: Lunch at Leschi Tavern**\n",
      "- Dock at Leschi Tavern for a casual lunch by the water.\n",
      "\n",
      "**1:30 PM - 2:30 PM: Boating to Magnuson Park**\n",
      "- Continue your boating adventure and head towards Magnuson Park.\n",
      "\n",
      "**2:30 PM - 3:30 PM: Swimming at Magnuson Park Beach**\n",
      "- Arrive at Magnuson Park and enjoy a swim in the lake. Relax on the sandy beach.\n",
      "\n",
      "**3:30 PM - 4:30 PM: Explore Magnuson Park**\n",
      "- Take a leisurely walk around the park, enjoying the natural beauty and playground.\n",
      "\n",
      "**4:30 PM - 5:00 PM: Return Boat and Drive to White-Water Rafting Location**\n",
      "- Return your boat and drive to the white-water rafting location (e.g., Skykomish River).\n",
      "\n",
      "**5:00 PM - 6:30 PM: White-Water Rafting**\n",
      "- Join a guided rafting trip for an exhilarating adventure on the rapids.\n",
      "\n",
      "**6:30 PM - 7:30 PM: Dinner at a Local Restaurant**\n",
      "- Enjoy dinner at a local restaurant in the area, such as Skykomish River Inn.\n",
      "\n",
      "**7:30 PM - 8:30 PM: Return Home**\n",
      "- Head back home, wrapping up a fantastic day of boating, swimming, and white-water rafting in Seattle.\n"
     ]
    }
   ],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "\n",
    "user_request = \"Can you add white water rafting to this itinerary\"\n",
    "display_markdown(Markdown(run_travel_planner(user_request, config)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Run with another session\n",
    "\n",
    "Now this session will not have the previous conversations and we see it will create a new travel plan with the `white water rafting`  interests, not boating or swim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:25:39.301581Z",
     "start_time": "2025-02-13T20:25:36.568798Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current User Request: Can you add white water rafting to itinerary\n",
      "\n",
      "\n",
      "Final Itinerary:\n",
      "Certainly! Here's a day trip itinerary for Seattle that includes white water rafting based on your interests:\n",
      "\n",
      "**Seattle Day Trip Itinerary**\n",
      "\n",
      "- **8:00 AM - Breakfast at The Crumpet House**\n",
      "  - Enjoy a delicious breakfast to fuel your day.\n",
      "\n",
      "- **9:30 AM - Pike Place Market**\n",
      "  - Explore the famous market, visit stalls, and enjoy the fresh produce and local crafts.\n",
      "\n",
      "- **11:00 AM - Space Needle**\n",
      "  - Take a trip to the iconic Space Needle for panoramic views of the city.\n",
      "\n",
      "- **12:30 PM - Lunch at Pike Place Chowder**\n",
      "  - Savor some clam chowder and fresh seafood.\n",
      "\n",
      "- **2:00 PM - Chihuly Garden and Glass**\n",
      "  - Marvel at the stunning glass art installations in the garden.\n",
      "\n",
      "- **3:30 PM - White Water Rafting on the Green River**\n",
      "  - Head out for an exhilarating white water rafting adventure.\n",
      "\n",
      "- **6:00 PM - Dinner at The Pink Door**\n",
      "  - Enjoy a delicious Italian meal in the heart of Seattle.\n",
      "\n",
      "- **7:30 PM - Evening Stroll in Pioneer Square**\n",
      "  - Take a leisurely walk through this historic area and enjoy the nightlife.\n",
      "\n",
      "- **9:00 PM - Drinks at The Crocodile**\n",
      "  - End your day with a drink at this famous Seattle jazz venue.\n",
      "\n",
      "Enjoy your adventure in Seattle!\n"
     ]
    }
   ],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"11\"}}\n",
    "\n",
    "user_request = \"Can you add white water rafting to itinerary\"\n",
    "display_markdown(Markdown(run_travel_planner(user_request, config)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Explore `External Store` for memory\n",
    "\n",
    "\n",
    "For Memory we further need short term and long term memory which can be explained below. Further reading can be at this [link](https://langchain-ai.github.io/langgraph/concepts/memory/#what-is-memory)\n",
    "\n",
    "Conversation memory can be explained by this diagram below which explains the `turn by turn` conversations which needs to be accessed by agents and then saved as a summary for long term memory\n",
    "\n",
    "![long term memory](./images/short-vs-long.png)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Create a `Store`\n",
    "\n",
    "In this section we will leverage multi-thread, multi-session persistence to Chat Messages. Ideally you will leverage persistence like Redis Store etc to save messages per session"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:25:41.814635Z",
     "start_time": "2025-02-13T20:25:41.808340Z"
    }
   },
   "outputs": [],
   "source": [
    "from langgraph.store.base import BaseStore, Item, Op, Result\n",
    "from langgraph.store.memory import InMemoryStore\n",
    "from typing import Any, Iterable, Literal, NamedTuple, Optional, Union, cast\n",
    "\n",
    "class CustomMemoryStore(BaseStore):\n",
    "\n",
    "    def __init__(self, ext_store):\n",
    "        self.store = ext_store\n",
    "\n",
    "    def get(self, namespace: tuple[str, ...], key: str) -> Optional[Item]:\n",
    "        return self.store.get(namespace,key)\n",
    "\n",
    "    def put(self, namespace: tuple[str, ...], key: str, value: dict[str, Any]) -> None:\n",
    "        return self.store.put(namespace, key, value)\n",
    "    def batch(self, ops: Iterable[Op]) -> list[Result]:\n",
    "        return self.store.batch(ops)\n",
    "    async def abatch(self, ops: Iterable[Op]) -> list[Result]:\n",
    "        return self.store.abatch(ops)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Quick look at how to use this store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:25:51.529968Z",
     "start_time": "2025-02-13T20:25:51.526881Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'data': ['list a']} ['list a']\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[('chat_messages', 'user_id_1')]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "in_memory_store = CustomMemoryStore(InMemoryStore())\n",
    "namespace_u = (\"chat_messages\", \"user_id_1\")\n",
    "key_u=\"user_id_1\"\n",
    "in_memory_store.put(namespace_u, key_u, {\"data\":[\"list a\"]})\n",
    "item_u = in_memory_store.get(namespace_u, key_u)\n",
    "print(item_u.value, item_u.value['data'])\n",
    "\n",
    "in_memory_store.list_namespaces()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Create the similiar graph as earlier -- note we will not have any mesages in the Graph state as that has been externalized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:25:52.740482Z",
     "start_time": "2025-02-13T20:25:52.738685Z"
    }
   },
   "outputs": [],
   "source": [
    "class PlannerState(TypedDict):\n",
    "    itinerary: str\n",
    "    city: str\n",
    "    user_message: str"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:25:54.039302Z",
     "start_time": "2025-02-13T20:25:54.035770Z"
    }
   },
   "outputs": [],
   "source": [
    "def input_interests(state: PlannerState, config: RunnableConfig, *, store: BaseStore) -> PlannerState:\n",
    "    user_message = state['user_message'] #input(\"Your input: \")\n",
    "    return {\n",
    "        **state,\n",
    "    }\n",
    "\n",
    "def create_itinerary(state: PlannerState, config: RunnableConfig, *, store: BaseStore) -> PlannerState:\n",
    "    #- get the history from the store\n",
    "    user_u = f\"user_id_{config['configurable']['thread_id']}\"\n",
    "    namespace_u = (\"chat_messages\", user_u)\n",
    "    store_item = store.get(namespace=namespace_u, key=user_u)\n",
    "    chat_history_messages = store_item.value['data'] if store_item else []\n",
    "    print(user_u,chat_history_messages)\n",
    "\n",
    "    response = llm.invoke(itinerary_prompt.format_messages(city=state['city'], user_message=state['user_message'], chat_history=chat_history_messages))\n",
    "    print(\"\\nFinal Itinerary:\")\n",
    "    print(response.content)\n",
    "\n",
    "    #- add back to the store\n",
    "    store.put(namespace=namespace_u, key=user_u, value={\"data\":chat_history_messages+[HumanMessage(content=state['user_message']),AIMessage(content=response.content)]})\n",
    "    \n",
    "    return {\n",
    "        **state,\n",
    "        \"itinerary\": response.content\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:26:03.477299Z",
     "start_time": "2025-02-13T20:26:03.472729Z"
    }
   },
   "outputs": [],
   "source": [
    "in_memory_store_n = CustomMemoryStore(InMemoryStore())\n",
    "\n",
    "workflow = StateGraph(PlannerState)\n",
    "workflow.add_node(\"input_interests\", input_interests)\n",
    "workflow.add_node(\"create_itinerary\", create_itinerary)\n",
    "workflow.set_entry_point(\"input_interests\")\n",
    "workflow.add_edge(\"input_interests\", \"create_itinerary\")\n",
    "workflow.add_edge(\"create_itinerary\", END)\n",
    "\n",
    "\n",
    "app = workflow.compile(store=in_memory_store_n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:27:07.980850Z",
     "start_time": "2025-02-13T20:27:04.092928Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "Can you create a itinerary for boating, swim. Need a complete plan"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "user_id_1 [HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Sure, here's a day trip itinerary for Seattle focusing on boating and swimming:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound. \\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you add itinerary for white water rafting to this', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Absolutely, here's an updated itinerary that includes white water rafting:\\n\\n**Seattle Boating, Swimming, and Whitewater Rafting Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Whitewater Rafting on the Snoqualmie River**\\n  - Head to the Snoqualmie River for an exhilarating white water rafting adventure. \\n\\n- **6:30 PM - 8:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating, swimming, and white water rafting.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Certainly! Here's a complete itinerary for a day of boating and swimming in Seattle:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\\n\\nThis itinerary provides a full day of boating and swimming in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\", additional_kwargs={}, response_metadata={})]\n",
      "\n",
      "Final Itinerary:\n",
      "Absolutely! Here's a complete itinerary for a day of boating and swimming in Seattle:\n",
      "\n",
      "**Seattle Boating and Swimming Day Trip Itinerary**\n",
      "\n",
      "- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\n",
      "  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\n",
      "\n",
      "- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\n",
      "  - Head to Leschi Park and rent a kayak or paddleboard for the day.\n",
      "\n",
      "- **11:00 AM - 1:00 PM: Boating on Lake Union**\n",
      "  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\n",
      "\n",
      "- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\n",
      "  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\n",
      "\n",
      "- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\n",
      "  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\n",
      "\n",
      "- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\n",
      "  - Head to Alki Beach for a refreshing swim in the Puget Sound.\n",
      "\n",
      "- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\n",
      "  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\n",
      "\n",
      "- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\n",
      "  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\n",
      "\n",
      "- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\n",
      "  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\n",
      "\n",
      "- **8:00 PM: Return Home**\n",
      "  - Head back home after a day filled with boating and swimming.\n",
      "\n",
      "This itinerary provides a full day of boating and swimming in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\n"
     ]
    }
   ],
   "source": [
    "def run_travel_planner(user_request: str, config_dict: dict):\n",
    "    display_markdown(Markdown(user_request))\n",
    "    init_input = {\"user_message\": user_request,\"city\" : \"Seattle\"}\n",
    "\n",
    "    for output in app.stream(init_input, config=config_dict, stream_mode=\"values\"):\n",
    "        pass  # The nodes themselves now handle all printing\n",
    "\n",
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "\n",
    "user_request = \"Can you create a itinerary for boating, swim. Need a complete plan\"\n",
    "run_travel_planner(user_request, config)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:27:30.659616Z",
     "start_time": "2025-02-13T20:27:26.555248Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "Can you add itinerary for white water rafting to this"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "user_id_1 [HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Sure, here's a day trip itinerary for Seattle focusing on boating and swimming:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound. \\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you add itinerary for white water rafting to this', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Absolutely, here's an updated itinerary that includes white water rafting:\\n\\n**Seattle Boating, Swimming, and Whitewater Rafting Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Whitewater Rafting on the Snoqualmie River**\\n  - Head to the Snoqualmie River for an exhilarating white water rafting adventure. \\n\\n- **6:30 PM - 8:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating, swimming, and white water rafting.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Certainly! Here's a complete itinerary for a day of boating and swimming in Seattle:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\\n\\nThis itinerary provides a full day of boating and swimming in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Absolutely! Here's a complete itinerary for a day of boating and swimming in Seattle:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\\n\\nThis itinerary provides a full day of boating and swimming in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\", additional_kwargs={}, response_metadata={})]\n",
      "\n",
      "Final Itinerary:\n",
      "Sure, here's an updated itinerary that includes white water rafting:\n",
      "\n",
      "**Seattle Boating, Swimming, and Whitewater Rafting Day Trip Itinerary**\n",
      "\n",
      "- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\n",
      "  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\n",
      "\n",
      "- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\n",
      "  - Head to Leschi Park and rent a kayak or paddleboard for the day.\n",
      "\n",
      "- **11:00 AM - 1:00 PM: Boating on Lake Union**\n",
      "  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\n",
      "\n",
      "- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\n",
      "  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\n",
      "\n",
      "- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\n",
      "  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\n",
      "\n",
      "- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\n",
      "  - Head to Alki Beach for a refreshing swim in the Puget Sound.\n",
      "\n",
      "- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\n",
      "  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\n",
      "\n",
      "- **5:00 PM - 6:00 PM: Whitewater Rafting on the Snoqualmie River**\n",
      "  - Head to the Snoqualmie River for an exhilarating white water rafting adventure.\n",
      "\n",
      "- **6:30 PM - 8:00 PM: Dinner at The Walrus and the Carpenter**\n",
      "  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\n",
      "\n",
      "- **8:00 PM: Return Home**\n",
      "  - Head back home after a day filled with boating, swimming, and white water rafting.\n",
      "\n",
      "This itinerary provides a full day of boating, swimming, and white water rafting in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\n"
     ]
    }
   ],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "\n",
    "user_request = \"Can you add itinerary for white water rafting to this\"\n",
    "run_travel_planner(user_request, config)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Quick look at the store\n",
    "\n",
    "it will show the History of the Chat Messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:27:30.674534Z",
     "start_time": "2025-02-13T20:27:30.671809Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('chat_messages', 'user_id_1')]\n",
      "{'data': [HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Sure, here's a day trip itinerary for Seattle focusing on boating and swimming:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound. \\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you add itinerary for white water rafting to this', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Absolutely, here's an updated itinerary that includes white water rafting:\\n\\n**Seattle Boating, Swimming, and Whitewater Rafting Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Whitewater Rafting on the Snoqualmie River**\\n  - Head to the Snoqualmie River for an exhilarating white water rafting adventure. \\n\\n- **6:30 PM - 8:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating, swimming, and white water rafting.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Certainly! Here's a complete itinerary for a day of boating and swimming in Seattle:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\\n\\nThis itinerary provides a full day of boating and swimming in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you create a itinerary for boating, swim. Need a complete plan', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Absolutely! Here's a complete itinerary for a day of boating and swimming in Seattle:\\n\\n**Seattle Boating and Swimming Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **6:30 PM - 8:00 PM: Sunset at Kerry Park**\\n  - End your day with a stunning sunset view at Kerry Park, a short drive from Alki Beach.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating and swimming.\\n\\nThis itinerary provides a full day of boating and swimming in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\", additional_kwargs={}, response_metadata={}), HumanMessage(content='Can you add itinerary for white water rafting to this', additional_kwargs={}, response_metadata={}), AIMessage(content=\"Sure, here's an updated itinerary that includes white water rafting:\\n\\n**Seattle Boating, Swimming, and Whitewater Rafting Day Trip Itinerary**\\n\\n- **8:00 AM - 9:00 AM: Breakfast at The Market's Edge**\\n  - Enjoy a hearty breakfast at this popular spot in Pioneer Square.\\n\\n- **9:30 AM - 11:00 AM: Rent a Boat at Leschi Park**\\n  - Head to Leschi Park and rent a kayak or paddleboard for the day.\\n\\n- **11:00 AM - 1:00 PM: Boating on Lake Union**\\n  - Paddle around Lake Union, taking in the views of the Seattle skyline and the University of Washington campus.\\n\\n- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\\n  - Enjoy a picnic lunch at Gas Works Park, a beautiful spot with views of the Seattle skyline and the industrial Gas Works Park.\\n\\n- **2:00 PM - 3:00 PM: Boating on Salmon Bay**\\n  - Continue your boating adventure over to Salmon Bay for more paddling and scenic views.\\n\\n- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\\n  - Head to Alki Beach for a refreshing swim in the Puget Sound.\\n\\n- **4:00 PM - 5:00 PM: Relax and Enjoy the Beach**\\n  - Spend some time relaxing on the beach, soaking up the sun, or exploring the nearby Alki Point.\\n\\n- **5:00 PM - 6:00 PM: Whitewater Rafting on the Snoqualmie River**\\n  - Head to the Snoqualmie River for an exhilarating white water rafting adventure.\\n\\n- **6:30 PM - 8:00 PM: Dinner at The Walrus and the Carpenter**\\n  - Enjoy a delicious dinner at this popular seafood restaurant in West Seattle.\\n\\n- **8:00 PM: Return Home**\\n  - Head back home after a day filled with boating, swimming, and white water rafting.\\n\\nThis itinerary provides a full day of boating, swimming, and white water rafting in Seattle, with plenty of time to relax and enjoy the beautiful scenery.\", additional_kwargs={}, response_metadata={})]}\n"
     ]
    }
   ],
   "source": [
    "print(in_memory_store_n.list_namespaces())\n",
    "print(in_memory_store_n.get(('chat_messages', 'user_id_1'),'user_id_1').value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Finally we review the concept of having Ecah `Agent` be backed by it's own memory\n",
    "\n",
    "For this we will leverage the RunnableWithMessageHistory when creating the agent\n",
    "- Here we create to simulate a InMemoryChatMessageHistory, but this will be externalized in produftion use cases\n",
    "- use this this as a sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:28:45.348129Z",
     "start_time": "2025-02-13T20:28:45.329945Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_core.chat_history import InMemoryChatMessageHistory\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
    "\n",
    "\n",
    "bedrock_client = boto3.client(\"bedrock-runtime\", region_name=\"us-west-2\")\n",
    "model_id = \"us.amazon.nova-lite-v1:0\"\n",
    "provider_id = \"amazon\"\n",
    "\n",
    "chatbedrock_llm = ChatBedrockConverse(\n",
    "    model=model_id,\n",
    "    provider=provider_id,\n",
    "    temperature=0,\n",
    "    max_tokens=None,\n",
    "    client=bedrock_client,\n",
    ")\n",
    "\n",
    "itinerary_prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"You are a helpful travel assistant. Create a day trip itinerary for {city} based on the user's interests. Use the below chat conversation and the latest input from Human to get the user interests. Provide a brief, bulleted itinerary.\"),\n",
    "    MessagesPlaceholder(\"chat_history\"),\n",
    "    (\"human\", \"{user_message}\"),\n",
    "])\n",
    "chain = itinerary_prompt | chatbedrock_llm \n",
    "\n",
    "history = InMemoryChatMessageHistory()\n",
    "def get_history():\n",
    "    return history\n",
    "\n",
    "wrapped_chain = RunnableWithMessageHistory(\n",
    "    chain,\n",
    "    get_history,\n",
    "    history_messages_key=\"chat_history\",\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:28:47.838213Z",
     "start_time": "2025-02-13T20:28:47.834774Z"
    }
   },
   "outputs": [],
   "source": [
    "class PlannerState(TypedDict):\n",
    "    itinerary: str\n",
    "    city: str\n",
    "    user_message: str\n",
    "\n",
    "def input_interests(state: PlannerState, config: RunnableConfig, *, store: BaseStore) -> PlannerState:\n",
    "    user_message = state['user_message'] #input(\"Your input: \")\n",
    "    return {\n",
    "        **state,\n",
    "    }\n",
    "\n",
    "def create_itinerary(state: PlannerState, config: RunnableConfig, *, store: BaseStore) -> PlannerState:\n",
    "    #- each agent manages it's memory\n",
    "    response = wrapped_chain.invoke({\"city\": state['city'], \"user_message\": state['user_message'], \"input\": state['user_message']} )\n",
    "    print(\"\\nFinal Itinerary:\")\n",
    "    print(response.content)\n",
    "    \n",
    "    return {\n",
    "        **state,\n",
    "        \"itinerary\": response.content\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:28:55.495757Z",
     "start_time": "2025-02-13T20:28:55.491726Z"
    }
   },
   "outputs": [],
   "source": [
    "workflow = StateGraph(PlannerState)\n",
    "\n",
    "workflow.add_node(\"input_interests\", input_interests)\n",
    "workflow.add_node(\"create_itinerary\", create_itinerary)\n",
    "workflow.set_entry_point(\"input_interests\")\n",
    "workflow.add_edge(\"input_interests\", \"create_itinerary\")\n",
    "workflow.add_edge(\"create_itinerary\", END)\n",
    "\n",
    "\n",
    "app = workflow.compile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:29:00.318334Z",
     "start_time": "2025-02-13T20:28:56.242278Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current User Request: Can you create a itinerary for boating, swim. Need a complete plan\n",
      "\n",
      "\n",
      "Final Itinerary:\n",
      "Sure! Here's a day trip itinerary for Seattle focusing on boating and swimming:\n",
      "\n",
      "**Seattle Boating and Swimming Day Trip Itinerary**\n",
      "\n",
      "- **8:00 AM - 9:00 AM: Breakfast at The Crumpet House**\n",
      "  - Enjoy a delicious breakfast to fuel your day.\n",
      "\n",
      "- **9:30 AM - 11:00 AM: Rent a Boat at Rent a Boat Seattle**\n",
      "  - Head to Rent a Boat Seattle to rent a boat for the day.\n",
      "\n",
      "- **11:00 AM - 1:00 PM: Boating on Lake Union**\n",
      "  - Explore the scenic Lake Union, taking in views of the city skyline and the iconic Space Needle.\n",
      "\n",
      "- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\n",
      "  - Enjoy a picnic lunch at the beautiful Gas Works Park, with its stunning views of the Seattle skyline and industrial remnants.\n",
      "\n",
      "- **2:00 PM - 3:00 PM: Boating on Puget Sound**\n",
      "  - Head out to Puget Sound for a change of scenery and some open water.\n",
      "\n",
      "- **3:00 PM - 4:00 PM: Swimming at Alki Beach**\n",
      "  - Dock at Alki Beach and take a refreshing swim in the Puget Sound.\n",
      "\n",
      "- **4:00 PM - 5:00 PM: Explore Alki Beach**\n",
      "  - Stroll along the beach, enjoy the sunset, and take in the vibrant atmosphere of Alki Beach.\n",
      "\n",
      "- **5:00 PM - 6:00 PM: Dinner at The Walrus and the Carpenter**\n",
      "  - Head back to the city and enjoy a delightful dinner at The Walrus and the Carpenter, known for its seafood and waterfront views.\n",
      "\n",
      "- **6:00 PM - 7:00 PM: Evening Walk at Waterfront Park**\n",
      "  - Take a leisurely evening walk along Waterfront Park, enjoying the beautiful views of the Seattle skyline and Elliott Bay.\n",
      "\n",
      "- **7:00 PM - 8:00 PM: Drinks at The Moore Tavern**\n",
      "  - End your day with a drink at The Moore Tavern, a historic bar with a great atmosphere.\n",
      "\n",
      "Enjoy your day in Seattle!\n"
     ]
    }
   ],
   "source": [
    "def run_travel_planner(user_request: str, config_dict: dict):\n",
    "    print(f\"Current User Request: {user_request}\\n\")\n",
    "    init_input = {\"user_message\": user_request,\"city\" : \"Seattle\"}\n",
    "\n",
    "    for output in app.stream(init_input, config=config_dict, stream_mode=\"values\"):\n",
    "        pass  # The nodes themselves now handle all printing\n",
    "\n",
    "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
    "\n",
    "user_request = \"Can you create a itinerary for boating, swim. Need a complete plan\"\n",
    "run_travel_planner(user_request, config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-13T20:29:06.377434Z",
     "start_time": "2025-02-13T20:29:02.197601Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current User Request: Can you add white water rafting to this itinerary\n",
      "\n",
      "\n",
      "Final Itinerary:\n",
      "Absolutely! Here's an updated itinerary that includes white-water rafting:\n",
      "\n",
      "**Seattle Boating, Swimming, and White-Water Rafting Day Trip Itinerary**\n",
      "\n",
      "- **8:00 AM - 9:00 AM: Breakfast at The Crumpet House**\n",
      "  - Enjoy a delicious breakfast to fuel your day.\n",
      "\n",
      "- **9:30 AM - 11:00 AM: Rent a Boat at Rent a Boat Seattle**\n",
      "  - Head to Rent a Boat Seattle to rent a boat for the day.\n",
      "\n",
      "- **11:00 AM - 1:00 PM: Boating on Lake Union**\n",
      "  - Explore the scenic Lake Union, taking in views of the city skyline and the iconic Space Needle.\n",
      "\n",
      "- **1:00 PM - 2:00 PM: Lunch at Gas Works Park**\n",
      "  - Enjoy a picnic lunch at the beautiful Gas Works Park, with its stunning views of the Seattle skyline and industrial remnants.\n",
      "\n",
      "- **2:00 PM - 3:00 PM: Boating on Puget Sound**\n",
      "  - Head out to Puget Sound for a change of scenery and some open water.\n",
      "\n",
      "- **3:00 PM - 4:00 PM: White-Water Rafting with Northwest Rafting Company**\n",
      "  - Head to Northwest Rafting Company for an exhilarating white-water rafting adventure on the White River.\n",
      "\n",
      "- **4:00 PM - 5:00 PM: Swimming at Alki Beach**\n",
      "  - Dock at Alki Beach and take a refreshing swim in the Puget Sound.\n",
      "\n",
      "- **5:00 PM - 6:00 PM: Explore Alki Beach**\n",
      "  - Stroll along the beach, enjoy the sunset, and take in the vibrant atmosphere of Alki Beach.\n",
      "\n",
      "- **6:00 PM - 7:00 PM: Dinner at The Walrus and the Carpenter**\n",
      "  - Head back to the city and enjoy a delightful dinner at The Walrus and the Carpenter, known for its seafood and waterfront views.\n",
      "\n",
      "- **7:00 PM - 8:00 PM: Evening Walk at Waterfront Park**\n",
      "  - Take a leisurely evening walk along Waterfront Park, enjoying the beautiful views of the Seattle skyline and Elliott Bay.\n",
      "\n",
      "- **8:00 PM - 9:00 PM: Drinks at The Moore Tavern**\n",
      "  - End your day with a drink at The Moore Tavern, a historic bar with a great atmosphere.\n",
      "\n",
      "Enjoy your adventurous day in Seattle!\n"
     ]
    }
   ],
   "source": [
    "user_request = \"Can you add white water rafting to this itinerary\"\n",
    "run_travel_planner(user_request, config)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "You have successfully executed a simple LangGraph implementation, this lab demonstrates how LangGraph can be used to create a simple yet effective Travel Planner. By structuring our application as a graph of interconnected nodes, we achieve a clear separation of concerns and a easily modifiable workflow. This approach can be extended to more complex applications, showcasing the power and flexibility of graph-based designs in AI-driven conversational interfaces.\n",
    "\n",
    "Please proceed to the next lab"
   ]
  }
 ],
 "metadata": {
  "availableInstances": [
   {
    "_defaultOrder": 0,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.t3.medium",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 1,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.t3.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 2,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.t3.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 3,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.t3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 4,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 5,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 6,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 7,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 8,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 9,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 10,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 11,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 12,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5d.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 13,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5d.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 14,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5d.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 15,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5d.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 16,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5d.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 17,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5d.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 18,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5d.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 19,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 20,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": true,
    "memoryGiB": 0,
    "name": "ml.geospatial.interactive",
    "supportedImageNames": [
     "sagemaker-geospatial-v1-0"
    ],
    "vcpuNum": 0
   },
   {
    "_defaultOrder": 21,
    "_isFastLaunch": true,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.c5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 22,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.c5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 23,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.c5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 24,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.c5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 25,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 72,
    "name": "ml.c5.9xlarge",
    "vcpuNum": 36
   },
   {
    "_defaultOrder": 26,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 96,
    "name": "ml.c5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 27,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 144,
    "name": "ml.c5.18xlarge",
    "vcpuNum": 72
   },
   {
    "_defaultOrder": 28,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.c5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 29,
    "_isFastLaunch": true,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g4dn.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 30,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g4dn.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 31,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g4dn.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 32,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g4dn.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 33,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g4dn.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 34,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g4dn.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 35,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 61,
    "name": "ml.p3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 36,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 244,
    "name": "ml.p3.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 37,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 488,
    "name": "ml.p3.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 38,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.p3dn.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 39,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.r5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 40,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.r5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 41,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.r5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 42,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.r5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 43,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.r5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 44,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.r5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 45,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.r5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 46,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.r5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 47,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 48,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 49,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 50,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 51,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 52,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 53,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.g5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 54,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.g5.48xlarge",
    "vcpuNum": 192
   },
   {
    "_defaultOrder": 55,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 56,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4de.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 57,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.trn1.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 58,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1.32xlarge",
    "vcpuNum": 128
   },
   {
    "_defaultOrder": 59,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1n.32xlarge",
    "vcpuNum": 128
   }
  ],
  "instance_type": "ml.t3.medium",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
